package com.wenx.v3system.modular.platform.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wenx.v3dynamicdatasourcestarter.config.DynamicDataSourceConfig;
import com.wenx.v3system.modular.platform.domain.dto.PlatformTenantDto;
import com.wenx.v3system.modular.platform.domain.po.PlatformTenant;
import com.wenx.v3system.modular.platform.domain.query.PlatformTenantQuery;
import com.wenx.v3system.modular.platform.mapper.PlatformTenantMapper;
import com.wenx.v3system.modular.platform.service.PlatformTenantService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 平台租户服务实现类
 * 使用v3-platform数据源
 * 
 * @author wenx
 */
@Service
@DS(DynamicDataSourceConfig.PLATFORM_DATASOURCE)
public class PlatformTenantServiceImpl implements PlatformTenantService {

    private static final Logger log = LoggerFactory.getLogger(PlatformTenantServiceImpl.class);
    
    private final PlatformTenantMapper platformTenantMapper;
    
    public PlatformTenantServiceImpl(PlatformTenantMapper platformTenantMapper) {
        this.platformTenantMapper = platformTenantMapper;
    }

    @Override
    public IPage<?> page(PlatformTenantQuery query) {
        Page<PlatformTenant> page = new Page<>(query.getCurrent(), query.getSize());
        
        // 构建动态查询条件
        LambdaQueryWrapper<PlatformTenant> wrapper = new LambdaQueryWrapper<>();
        
        // 根据查询条件动态拼接参数
        if (StringUtils.hasText(query.getCode())) {
            wrapper.like(PlatformTenant::getCode, query.getCode());
        }
        if (StringUtils.hasText(query.getName())) {
            wrapper.like(PlatformTenant::getName, query.getName());
        }
        if (StringUtils.hasText(query.getDomain())) {
            wrapper.like(PlatformTenant::getDomain, query.getDomain());
        }
        if (StringUtils.hasText(query.getContactName())) {
            wrapper.like(PlatformTenant::getContactName, query.getContactName());
        }
        if (StringUtils.hasText(query.getContactEmail())) {
            wrapper.like(PlatformTenant::getContactEmail, query.getContactEmail());
        }
        if (query.getStatus() != null) {
            wrapper.eq(PlatformTenant::getStatus, query.getStatus());
        }
        if (StringUtils.hasText(query.getPlanType())) {
            wrapper.eq(PlatformTenant::getPlanType, query.getPlanType());
        }
        if (query.getMinUsers() != null) {
            wrapper.ge(PlatformTenant::getMaxUsers, query.getMinUsers());
        }
        if (query.getMaxUsers() != null) {
            wrapper.le(PlatformTenant::getMaxUsers, query.getMaxUsers());
        }
        if (query.getIsExpiringSoon() != null && query.getIsExpiringSoon()) {
            // 查询30天内即将过期的租户
            Date thirtyDaysLater = DateUtils.addDays(new Date(), 30);
            wrapper.le(PlatformTenant::getExpireTime, thirtyDaysLater)
                   .gt(PlatformTenant::getExpireTime, new Date());
        }
        
        // 按创建时间倒序排列
        wrapper.orderByDesc(PlatformTenant::getCreateTime);
        
        IPage<PlatformTenant> result = platformTenantMapper.selectPage(page, wrapper);
        // 转换为DTO
        return result.convert(this::convertToDto);
    }

    @Override
    public Object get(Serializable id) {
        PlatformTenant tenant = platformTenantMapper.selectTenantWithStatsById((Long) id);
        if (tenant == null) {
            throw new RuntimeException("租户不存在");
        }
        return convertToDto(tenant);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(PlatformTenantDto dto) {
        // 检查编码是否存在
        if (checkCodeExists(dto.getCode(), null)) {
            throw new RuntimeException("租户编码已存在");
        }
        
        // 检查域名是否存在
        if (StringUtils.hasText(dto.getDomain()) && checkDomainExists(dto.getDomain(), null)) {
            throw new RuntimeException("域名已存在");
        }

        PlatformTenant tenant = new PlatformTenant();
        BeanUtils.copyProperties(dto, tenant);
        
        // 设置默认值
        tenant.setStatus(1); // 默认正常状态
        tenant.setCurrentUsers(0);
        tenant.setExpireTime(DateUtils.addYears(new Date(), 1)); // 默认1年过期
        
        // 生成数据库Schema名称
        if (!StringUtils.hasText(tenant.getDatabaseName())) {
            tenant.setDatabaseName("tenant_" + tenant.getCode() + "_db");
        }
        
        platformTenantMapper.insert(tenant);
        
        log.info("租户创建成功: tenantId={}, code={}", tenant.getId(), tenant.getCode());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Serializable id) {
        deleteTenant(Long.valueOf(id.toString()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(PlatformTenantDto dto) {
        if (dto.getId() == null) {
            throw new RuntimeException("租户ID不能为空");
        }
        
        PlatformTenant existingTenant = platformTenantMapper.selectById(dto.getId());
        if (existingTenant == null) {
            throw new RuntimeException("租户不存在");
        }
        
        // 检查编码是否重复
        if (checkCodeExists(dto.getCode(), dto.getId())) {
            throw new RuntimeException("租户编码已存在");
        }
        
        // 检查域名是否重复
        if (StringUtils.hasText(dto.getDomain()) && checkDomainExists(dto.getDomain(), dto.getId())) {
            throw new RuntimeException("域名已存在");
        }

        PlatformTenant tenant = new PlatformTenant();
        BeanUtils.copyProperties(dto, tenant);
        
        platformTenantMapper.updateById(tenant);
        
        log.info("租户更新成功: tenantId={}", dto.getId());
    }

    @Override
    public PlatformTenantDto getTenantById(Long id) {
        PlatformTenant tenant = platformTenantMapper.selectById(id);
        return tenant != null ? convertToDto(tenant) : null;
    }

    @Override
    public PlatformTenantDto getTenantByCode(String code) {
        PlatformTenant tenant = platformTenantMapper.selectTenantByCode(code);
        return tenant != null ? convertToDto(tenant) : null;
    }

    @Override
    public PlatformTenantDto getTenantByDomain(String domain) {
        PlatformTenant tenant = platformTenantMapper.selectTenantByDomain(domain);
        return tenant != null ? convertToDto(tenant) : null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PlatformTenantDto createTenant(PlatformTenantDto tenantDto) {
        add(tenantDto);
        return getTenantById(tenantDto.getId());
    }



    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteTenant(Long tenantId) {
        PlatformTenant tenant = platformTenantMapper.selectById(tenantId);
        if (tenant == null) {
            throw new RuntimeException("租户不存在");
        }
        
        // 逻辑删除租户
        platformTenantMapper.deleteById(tenantId);
        
        log.info("租户删除成功: tenantId={}, code={}", tenantId, tenant.getCode());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTenantStatus(Long tenantId, Integer status) {
        PlatformTenant tenant = new PlatformTenant();
        tenant.setId(tenantId);
        tenant.setStatus(status);
        
        platformTenantMapper.updateById(tenant);
        
        log.info("租户状态更新成功: tenantId={}, status={}", tenantId, status);
    }

    @Override
    public List<PlatformTenantDto> getExpiringTenants(Integer days) {
        List<PlatformTenant> tenants = platformTenantMapper.selectExpiringTenants(days);
        return tenants.stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());
    }

    @Override
    public List<PlatformTenantDto> getActiveTenants(Integer days) {
        List<PlatformTenant> tenants = platformTenantMapper.selectActiveTenants(days);
        return tenants.stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());
    }

    @Override
    public boolean checkCodeExists(String code, Long tenantId) {
        LambdaQueryWrapper<PlatformTenant> wrapper = new LambdaQueryWrapper<PlatformTenant>()
            .eq(PlatformTenant::getCode, code)
            .eq(PlatformTenant::getDeleted, 0);
        
        if (tenantId != null) {
            wrapper.ne(PlatformTenant::getId, tenantId);
        }
        
        return platformTenantMapper.selectCount(wrapper) > 0;
    }

    @Override
    public boolean checkDomainExists(String domain, Long tenantId) {
        if (!StringUtils.hasText(domain)) {
            return false;
        }
        
        LambdaQueryWrapper<PlatformTenant> wrapper = new LambdaQueryWrapper<PlatformTenant>()
            .eq(PlatformTenant::getDomain, domain)
            .eq(PlatformTenant::getDeleted, 0);
        
        if (tenantId != null) {
            wrapper.ne(PlatformTenant::getId, tenantId);
        }
        
        return platformTenantMapper.selectCount(wrapper) > 0;
    }


    /**
     * 转换为DTO
     */
    private PlatformTenantDto convertToDto(PlatformTenant tenant) {
        PlatformTenantDto dto = new PlatformTenantDto();
        BeanUtils.copyProperties(tenant, dto);
        
        // 计算使用率
        if (tenant.getMaxUsers() != null && tenant.getMaxUsers() > 0) {
            double rate = (double) tenant.getCurrentUsers() / tenant.getMaxUsers() * 100;
            dto.setUserUsageRate(Math.round(rate * 100.0) / 100.0);
        }
        
        // 判断是否即将过期
        if (tenant.getExpireTime() != null) {
            Date thirtyDaysFromNow = DateUtils.addDays(new Date(), 30);
            boolean expiringSoon = tenant.getExpireTime().before(thirtyDaysFromNow);
            dto.setIsExpiringSoon(expiringSoon);
        }
        
        return dto;
    }

    @Override
    public Map<String, Object> getTenantUsage(Long tenantId) {
        PlatformTenant tenant = platformTenantMapper.selectById(tenantId);
        if (tenant == null) {
            throw new RuntimeException("租户不存在");
        }
        
        Map<String, Object> usage = new HashMap<>();
        usage.put("currentUsers", tenant.getCurrentUsers());
        usage.put("maxUsers", tenant.getMaxUsers());
        usage.put("userUsageRate", tenant.getMaxUsers() != null && tenant.getMaxUsers() > 0 
            ? (double) tenant.getCurrentUsers() / tenant.getMaxUsers() * 100 : 0);
        usage.put("expireTime", tenant.getExpireTime());
        usage.put("isExpiringSoon", tenant.getExpireTime() != null && 
            tenant.getExpireTime().before(DateUtils.addDays(new Date(), 30)));
        
        return usage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void extendTenantExpiry(Long tenantId, Integer months) {
        PlatformTenant tenant = platformTenantMapper.selectById(tenantId);
        if (tenant == null) {
            throw new RuntimeException("租户不存在");
        }
        
        Date newExpireTime;
        if (tenant.getExpireTime() != null && tenant.getExpireTime().after(new Date())) {
            newExpireTime = DateUtils.addMonths(tenant.getExpireTime(), months);
        } else {
            newExpireTime = DateUtils.addMonths(new Date(), months);
        }
        
        tenant.setExpireTime(newExpireTime);
        platformTenantMapper.updateById(tenant);
        
        log.info("租户有效期延长成功: tenantId={}, months={}, newExpireTime={}", 
            tenantId, months, newExpireTime);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void upgradeTenantPlan(Long tenantId, String planType, Integer maxUsers) {
        PlatformTenant tenant = platformTenantMapper.selectById(tenantId);
        if (tenant == null) {
            throw new RuntimeException("租户不存在");
        }
        
        tenant.setPlanType(planType);
        tenant.setMaxUsers(maxUsers);
        platformTenantMapper.updateById(tenant);
        
        log.info("租户套餐升级成功: tenantId={}, planType={}, maxUsers={}", 
            tenantId, planType, maxUsers);
    }

}